<?php

namespace App\Http\Controllers\Api;

use App\Http\Requests\Api\TokenRequest;
use App\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;

/**
 * 令牌管理
 * Class TokenController
 * @package App\Http\Controllers\Api
 */
class TokenController extends BaseController
{
    /**
     * 创建令牌
     */
    public function createToken(TokenRequest $tokenRequest) {
//        try {
//            //$token = $user->createToken('token-name');
//            $i =  1 / 0;
//        } catch (\Exception $exception) {
//            return 'haha';//$exception->getMessage();
//        }

        try {
            $validated = $tokenRequest->validated();
            // print_r($validated);

            // 如果没有找到，$user 是 null。
            $user = User::query()->where(['email' => $validated['email']])->first();

            if ($user) {
                // optional($user)->getAuthPassword(); 就是数据库里保存的 hash 后的密码字符串。
                $validate = password_verify($validated['password'], optional($user)->getAuthPassword());
                $authUser = $validate ? $user : false;

                /*
                    表 personal_access_tokens 中有这么几个字段：
                    1、id，自增主键。
                    2、tokenable_type，模型类的全路径名称，App\User。
                    3、tokenable_id，users 表中 id 的值。
                    4、name，创建的 token 的名字。
                    5、token，创建的 token 的值。但不是返回给客户端的值。
                    6、abilities，默认都是 ["*"]，不过这个默认值不是数据表里设置的，而是 sanctum 提供的功能。
                    7、last_used_at，默认值是 null，只有在访问了 使用auth:sanctum 保护的路由才会有值。
                    8、created_at。
                    9、deleted_at。
                */
                /*
                    需要说明的是两点：
                    1、生成的 plainTextToken 的值是返回给客户端的，而存储在表 personal_access_tokens 中 token 字段的值并不是这个字符串，而是与之匹配的。
                    比如：
                    token 字段存储：070e9d89d252e7c2741aeac06109cf715cc9746880f5f02075dd59d7a5ba7440
                    plainTextToken 返回：HbM9p63XpJ8R8792VMDjqh6AFwi7ebLH7Bm5wuHFfdrb2nlH4nP2a22ucIqrmKwrIb3IsVAPOk6ctenT
                    2、表 personal_access_tokens 中 tokenable_id 字段的值是 users 表中 id 的值，即给哪个用户生成的 token。
                    3、表 personal_access_tokens 中同一个 tokenable_id、同一个 name，可以有多条记录，token 字段值不同，不过客户端得到的 plainTextToken 的值都有效果。
                    请求头：Accept: application/json，Authorization:Bearer plainTextToken值。
                */
                /*
                    我们应该怎么做？
                    由于给客户端返回的是并不是 token 字段的值，而 plainTextToken值 又没有在我们的表中存储过，所以只能每次都创建新的了。
                    既然创建新的 plainTextToken值，就有与之对应的新的 token，而且旧的 token 已经没有作用了，所以应该删除旧的。
                    这有个前提：就是 abilities 字段的值一样，此时就没必要多个 token 了，只有一个即可。
                 */

                // 这里，我们就认为 abilities 都是 ["*"]，这样就可以在创建之前，先删除旧的同名 token。

                $tokens = $authUser->tokens();
                // var_dump($tokens->getResults()->length);// Property [length] does not exist on this collection instance.
                // var_dump($tokens->getResults()->length());// Method Illuminate\\Database\\Eloquent\\Collection::length does not exist.

                // $result = $tokens->delete();// 2。就是成功删除的数据的条数。不过我们一般不关心删除是否成功，所以就不需要返回值了。

                // 有旧值，删除之。
                if (count($tokens->getResults()) > 0) {
                    $tokens->delete();
                }
                // exit;

                // 创建[新的]令牌，把 email 当作 name。
                 $token = $authUser->createToken($validated['email']);

                // var_dump(get_class($authUser->tokens()));// string(48) "Illuminate\Database\Eloquent\Relations\MorphMany"
                // 不能直接把 $authUser->tokens() 响应给客户端，postman 里提示超过了最大响应内容。Error: Maximum response size reached.

                // var_dump($tokens);// Error: Maximum response size reached.
                // var_dump($tokens->where('id', 1)->select());// Error: Maximum response size reached.
                // var_dump($tokens->where('id', 1)->find());// ArgumentCountError: Too few arguments to function Illuminate\Database\Eloquent\Builder::find(), 0 passed in D:\project\study\study-php-laravel-7120\app7120-sanctum-api\vendor\laravel\framework\src\Illuminate\Support\Traits\ForwardsCalls.php on line 23 and at least 1 expected in file D:\project\study\study-php-laravel-7120\app7120-sanctum-api\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Builder.php on line 339
                // var_dump($tokens->find(1));// object(Laravel\Sanctum\PersonalAccessToken)#1282 (27) { 正是 id=1 的数据。如果以json 返回，

                // var_dump($tokens->select());// Error: Maximum response size reached
                // var_dump(get_class($tokens->select()));// string(48) "Illuminate\Database\Eloquent\Relations\MorphMany"

                /*
                不能视为数组，$key、$value 什么都没有。
                foreach ($tokens->select() as $key => $value) {
                    var_dump($value);
                }
                */
                // $clazz = \Illuminate\Database\Eloquent\Relations\MorphMany::class;
                // var_dump($tokens->select()->getResults());
                /*
                object(Illuminate\Database\Eloquent\Collection)#1126 (1) {
                ["items":protected]=>
                array(2) {
                [0]=>
                object(Laravel\Sanctum\PersonalAccessToken)#1283 (27) {
                 */

                // var_dump($tokens->getResults());
                /*
                object(Illuminate\Database\Eloquent\Collection)#1126 (1) {
                ["items":protected]=>
                array(2) {
                [0]=>
                object(Laravel\Sanctum\PersonalAccessToken)#1283 (27) {
                 */

                // FKjb3jIB006tWwjAWj5xtobab5kgac3kvEAbwqromP6SRBgxabRSDwmUPyrWPuR86eZB0jGQm1IqaTzX

                return [
                    'errcode' => 200,
                    'message' => '创建令牌成功',
                    'data' => [
                        'token' => $token->plainTextToken
                        /*
                            'token' => $token
                                "token": {
                                    "accessToken": {
                                        "name": "678@qq.com",
                                        "abilities": [
                                                    "*"
                                                ],
                                        "tokenable_id": 10,
                                        "tokenable_type": "App\\User",
                                        "updated_at": "2021-04-29T07:49:23.000000Z",
                                        "created_at": "2021-04-29T07:49:23.000000Z",
                                        "id": 1
                                    },
                                    "plainTextToken": "HbM9p63XpJ8R8792VMDjqh6AFwi7ebLH7Bm5wuHFfdrb2nlH4nP2a22ucIqrmKwrIb3IsVAPOk6ctenT"
                                }
                        */

                        // 'tokens' => $authUser->tokens() // 不可。
                        /*
                            'aa' => $a->find(1)

                                "aa": {
                                    "id": 1,
                                    "tokenable_type": "App\\User",
                                    "tokenable_id": 10,
                                    "name": "678@qq.com",
                                    "abilities": [
                                        "*"
                                    ],
                                    "last_used_at": "2021-04-29T08:15:26.000000Z",
                                    "created_at": "2021-04-29T07:49:23.000000Z",
                                    "updated_at": "2021-04-29T08:15:26.000000Z"
                                }
                         */
                    ],
                ];
            }

            return [
                'errcode' => 200,
                'message' => '创建令牌成功',
                'data' => $user
            ];

            /*$user = new User();
            $user->name = $validated['name'];
            $user->email = $validated['email'];
            $user->password = Hash::make($validated['name']);
            // 成功，结果是 true。
            $result = $user->save();
            if (!$result) {
                Log::error('用户注册时保存数据库失败: name=' . $user->name . ', email=' . $user->email . ', password=' . $user->password . '.');
                return [
                    'errcode' => 4002,
                    'message' => '注册失败'
                ];
            }

            return [
                'errcode' => 200,
                'message' => '注册成功',
                'data' => $user
            ];*/
        } catch (\Exception $exception) {
//            Log::error('用户注册时保存数据库异常: name=' . $user->name . ', email=' . $user->email . ', password=' . $user->password . '.');
            Log::error('用户注册时保存数据库异常: exception=' . $exception->getMessage() . '.');
            return [
                'errcode' => 4000,
                'message' => '异常：' . $exception->getMessage()
            ];
        }
    }


}
